package cn.tedu.st.base.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

public class JwtUtil {

    // 默认过期时间（单位：毫秒，1小时）
    public static final Long JWT_TTL = 60 * 60 * 1000L;

    // 设置秘钥明文（盐，至少32字节）
    public static final String JWT_KEY = "abcdefghijklmnopqrstuvwxyz123456789";

    /**
     * 生成 UUID
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 创建 JWT
     *
     * @param subject   主题（通常是用户ID或用户名）
     * @param ttlMillis 过期时间（毫秒，可选）
     * @return JWT 字符串
     */
    public static String createJWT(String subject, Long ttlMillis) {
        if (ttlMillis == null) {
            ttlMillis = JWT_TTL; // 如果未指定过期时间，使用默认值
        }
        return getJwtBuilder(subject, ttlMillis, getUUID()).compact();
    }

    /**
     * 创建带有自定义 ID 的 JWT
     *
     * @param subject   主题（通常是用户ID或用户名）
     * @param ttlMillis 过期时间（毫秒，可选）
     * @param id        自定义 ID
     * @return JWT 字符串
     */
    public static String createJWT(String subject, Long ttlMillis, String id) {
        if (ttlMillis == null) {
            ttlMillis = JWT_TTL; // 如果未指定过期时间，使用默认值
        }
        return getJwtBuilder(subject, ttlMillis, id).compact();
    }

    /**
     * 获取 JWT 构建器
     */
    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);

        return Jwts.builder()
                .setId(uuid)                  // 唯一的 ID
                .setSubject(subject)          // 主题
                .setIssuer("xx")              // 签发者
                .setIssuedAt(now)             // 签发时间
                .signWith(signatureAlgorithm, secretKey) // 使用 HS256 对称加密算法签名
                .setExpiration(expDate);      // 过期时间
    }

    /**
     * 生成加密后的秘钥 secretKey
     */
    public static SecretKey generalKey() {
        byte[] keyBytes = JWT_KEY.getBytes(StandardCharsets.UTF_8);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 解析 JWT 并返回 Claims
     */
    public static Claims parseJWT(String jwt) throws JwtException {
        try {
            SecretKey secretKey = generalKey();
            return Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(jwt)
                    .getBody();
        } catch (ExpiredJwtException e) {
            throw new JwtException("Token 已过期", e);
        } catch (MalformedJwtException e) {
            throw new JwtException("Token 格式错误", e);
        } catch (SignatureException e) {
            throw new JwtException("Token 签名无效", e);
        } catch (Exception e) {
            throw new JwtException("Token 解析失败", e);
        }
    }
}